﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Workflow.Runtime.Hosting;
using System.Diagnostics;
using System.Workflow.Runtime;
using System.Workflow.ComponentModel;

namespace Bukovics.Workflow.Hosting
{
    [Serializable]
    public class FileWorkflowPersistenceService : WorkflowPersistenceService, IPendingWork
    {
        static readonly object _lock = new object();
        NameValueCollection _parameters;
        bool _unloadOnIdle = true;
        string _mainPath = string.Empty;

        public FileWorkflowPersistenceService()
        {
            init();
        }
        public FileWorkflowPersistenceService(NameValueCollection parameters)
        {
            _parameters = parameters;
            init();
        }

        public FileWorkflowPersistenceService(string path)
        {
            NameValueCollection parameters = new NameValueCollection();
            parameters["MainPath"] = path;
            _parameters = parameters;
            init();
        }

        private void init()
        {
            if (_parameters == null) _parameters = new NameValueCollection();

            _mainPath = string.Concat(_parameters["MainPath"]);



        }

        public List<Guid> GetAllWorkflows()
        {
            if (base.State == WorkflowRuntimeServiceState.Started)
            {
                return FileTools.GetAllWorkflows(_mainPath);
            }
            throw new InvalidOperationException("FileWorkflowPersistenceService not Started");
        }

        #region 重写序方法 WorkflowPersistenceService
        /// <summary>
        ///载入已完成的 activity 状态
        /// </summary>
        /// <param name="scopeId"></param>
        /// <param name="outerActivity"></param>
        /// <returns></returns>
        protected override System.Workflow.ComponentModel.Activity LoadCompletedContextActivity(Guid scopeId, System.Workflow.ComponentModel.Activity outerActivity)
        {
            Debug.WriteLine("LoadCompletedContextActivity");
            byte[] buffer1 = null;
            FileTools.LoadActivity(_mainPath, scopeId, out buffer1);
            return WorkflowPersistenceService.RestoreFromDefaultSerializedForm(buffer1, outerActivity);

        }
        /// <summary>
        /// 载入实例 activity 状态
        /// </summary>
        /// <param name="instanceId"></param>
        /// <returns></returns>
        protected override System.Workflow.ComponentModel.Activity LoadWorkflowInstanceState(Guid instanceId)
        {

            Debug.WriteLine("LoadWorkflowInstanceState");
            byte[] buffer1 = null;
            FileTools.LoadActivity(_mainPath, instanceId, out buffer1);
            return WorkflowPersistenceService.RestoreFromDefaultSerializedForm(buffer1, null);


        }
        /// <summary>
        /// 保存已完成的状态
        /// </summary>
        /// <param name="activity"></param>
        protected override void SaveCompletedContextActivity(System.Workflow.ComponentModel.Activity activity)
        {
            Debug.WriteLine("SaveCompletedContextActivity");
            PendingWorkItem item1 = new PendingWorkItem();
            item1.Type = PendingWorkItem.ItemType.CompletedScope;
            item1.SerializedActivity = WorkflowPersistenceService.GetDefaultSerializedForm(activity);
            item1.InstanceId = WorkflowEnvironment.WorkflowInstanceId;
            item1.StateId = (Guid)activity.GetValue(Activity.ActivityContextGuidProperty);
            WorkflowEnvironment.WorkBatch.Add(this, item1);
        }
        /// <summary>
        /// 保存实例
        /// </summary>
        /// <param name="rootActivity"></param>
        /// <param name="unlock"></param>
        protected override void SaveWorkflowInstanceState(System.Workflow.ComponentModel.Activity rootActivity, bool unlock)
        {
            Debug.WriteLine("SaveWorkflowInstanceState:" + unlock);
            if (rootActivity == null)
            {
                throw new ArgumentNullException("rootActivity");
            }
            WorkflowStatus status = WorkflowPersistenceService.GetWorkflowStatus(rootActivity);
            bool blocked = WorkflowPersistenceService.GetIsBlocked(rootActivity);
            string info = WorkflowPersistenceService.GetSuspendOrTerminateInfo(rootActivity);

            Guid stateId = (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty);

            PendingWorkItem item1 = new PendingWorkItem();

            item1.Type = PendingWorkItem.ItemType.Instance;
            item1.InstanceId = WorkflowEnvironment.WorkflowInstanceId;
            byte[] buffer1;
            if ((status != WorkflowStatus.Completed) && (status != WorkflowStatus.Terminated))
            {
                buffer1 = WorkflowPersistenceService.GetDefaultSerializedForm(rootActivity);
            }
            else
            {
                buffer1 = new byte[0];
            }
            item1.SerializedActivity = buffer1;
            item1.Status = (int)status;
            item1.Blocked = blocked ? 1 : 0;
            item1.Info = info;
            item1.StateId = stateId;
            item1.Unlocked = unlock;
            TimerEventSubscription subscription1 = ((TimerEventSubscriptionCollection)rootActivity.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty)).Peek();
            item1.NextTimer = (subscription1 == null) ? DateTime.MaxValue : ((DateTime)subscription1.ExpiresAt);
            if (item1.Info == null)
            {
                item1.Info = "";
            }


            WorkflowEnvironment.WorkBatch.Add(this, item1);

        }
        /// <summary>
        /// 返回对进入IDLE状态的实例的解决模式
        /// </summary>
        /// <param name="activity"></param>
        /// <returns></returns>
        protected override bool UnloadOnIdle(System.Workflow.ComponentModel.Activity activity)
        {
            Debug.WriteLine("UnloadOnIdle");
            return this._unloadOnIdle;

        }


        /// <summary>
        /// 对锁定的实例解锁 , 使实例可被操作
        /// </summary>
        /// <param name="rootActivity"></param>
        protected override void UnlockWorkflowInstanceState(System.Workflow.ComponentModel.Activity rootActivity)
        {
            //不过ms 是当作没用的处理的
            Debug.WriteLine("UnlockWorkflowInstanceState");

            PendingWorkItem item1 = new PendingWorkItem();
            item1.Type = PendingWorkItem.ItemType.ActivationComplete;
            item1.InstanceId = WorkflowEnvironment.WorkflowInstanceId;
            WorkflowEnvironment.WorkBatch.Add(this, item1);


        }
        #endregion

        #region IPendingWork 成员

        public void Commit(System.Transactions.Transaction transaction, System.Collections.ICollection items)
        {
            Debug.WriteLine("Commit");
            foreach (PendingWorkItem item1 in items)
            {
                switch (item1.Type)
                {
                    case PendingWorkItem.ItemType.Instance:
                        {

                            if (item1.Status == 1 || item1.Status == 3) //Completed or Terminated
                                FileTools.BakPendingWorkItem(this._mainPath, item1.InstanceId);
                            else
                                FileTools.SavePendingWorkItem(this._mainPath, item1);


                            break;
                        }
                    case PendingWorkItem.ItemType.CompletedScope:
                        {
                            throw new ApplicationException("Commit case PendingWorkItem.ItemType.CompletedScope");

                        }
                    case PendingWorkItem.ItemType.ActivationComplete:
                        {
                            FileTools.BakPendingWorkItem(this._mainPath, item1.InstanceId);
                            break;
                        }
                }

                //
            }
        }

        public void Complete(bool succeeded, System.Collections.ICollection items)
        {
            Debug.WriteLine("Complete");
            //if ((this.loadingTimer != null) && succeeded)
            //{
            //    foreach (PendingWorkItem item1 in items)
            //    {
            //        if (item1.Type.Equals(PendingWorkItem.ItemType.Instance))
            //        {
            //            this.loadingTimer.Update((DateTime)item1.NextTimer);
            //        }
            //    }
            //}

            if (succeeded)
            {
                //
            }
        }

        public bool MustCommit(System.Collections.ICollection items)
        {
            Debug.WriteLine("MustCommit");
            return true;
        }

        #endregion
    }
}
